#ifndef MULTIBOOT_H_
#define MULTIBOOT_H_

#include <types.h>

#define MULTIBOOT_HEADER_MAGIC	0x1BADB002
#define MULTIBOOT_PAGE_ALIGN	1<<0
#define MULTIBOOT_MEMORY_INFO	1<<1
#define MULTIBOOT_HEADER_FLAGS	MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
#define CHECKSUM				-(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002

#define MB_ERR_BADMAGIC 1

#define EBDA_PTR 0x40E

#ifndef ASM

#define CHECK_FLAG(flags,bit)   ((flags) & (1 << (bit)))

typedef struct multiboot_header
{
	dword magic;
	dword flags;
	dword checksum;
	dword header_addr;
	dword load_addr;
	dword load_end_addr;
	dword bss_end_addr;
	dword entry_addr;
} multiboot_header_t;

typedef struct multiboot_elf_section_header_table
{
	dword num;
	dword size;
	dword addr;
	dword shndx;
} multiboot_elf_section_header_table_t;

typedef struct multiboot_info
{
	dword flags;
	dword mem_lower;
	dword mem_upper;
	dword boot_device;
	dword cmdline;
	dword mods_count;
	dword mods_addr;
	union
	{
		//aout_symbol_table_t aout_sym;
		multiboot_elf_section_header_table_t elf_sec;
	} u;
	dword mmap_length;
	dword mmap_addr;
	dword drives_length;
	dword drives_addr;
	dword config_table;
	dword boot_loader_name;
	dword apm_table;
	dword vbe_control_info;
	dword vbe_mode_info;
	dword vbe_mode;
	dword vbe_interface_seg;
	dword vbe_interface_offset;
	dword vbe_interdace_length;
} multiboot_info_t;

typedef struct module
{
	dword mod_start;
	dword mod_end;
	dword string;
	dword reserved;
} module_t;

typedef struct memory_map
{
	dword size;
	dword base_addr_low;
	dword base_addr_high;
	dword length_low;
	dword length_high;
	dword type;
} memory_map_t;

extern size_t g_lowmem;
extern size_t g_highmem;

int check_multiboot_magic(dword magic);
void init_multiboot_info(multiboot_info_t *mbi);
dword get_ebda_addr(void);

#endif

#endif /*MULTIBOOT_H_*/
